﻿using System;
using System.Linq;

using Buddy.BehaviorTree;
using Buddy.Common;
using Buddy.CommonBot;
using Buddy.Swtor;
using Buddy.Swtor.Objects;

using WingIt;
using WingIt.Dynamics;
using WingIt.Routines.Mirrors;


namespace WingIt.Routines
{
    //Neo93
    [RevisionControlId("$Id: Lightning_Telekinetics.cs 686 2012-08-12 16:12:20Z Chinajade $")]
    public class SorcererLightning_SageTelekinetics : MirrorRoutine
    {
        // MAINTAINERS NOTES:
        // * You will notice that lambda expression argument names are unique (e.g., "darkWardOn", "darkWardWhen", "joltWhen"),
        //   instead of generic (e.g., "ctx", "ret", "on", "doWhen", "castWhen").  PLEASE honor this convention!
        //   This allows us to quickly localize problems when looking at user's logs.  When the BehaviorTree encounters an exception
        //   (e.g., "object not found"), the location where an exception is thrown is identifiable only through the name
        //   of the lambda expression argument.  Such is the nature of BehaviorTrees.

        [Behavior(BehaviorType.Pull)]
        [Class(CharacterClass.Inquisitor, AdvancedClass.Sorcerer, SkillTreeId.SorcererLightning)]
        [Class(CharacterClass.Consular, AdvancedClass.Sage, SkillTreeId.SageTelekinetics)]
        public static Composite SorcererLightning_SageTelekinetics_Pull()
        {
            return new PrioritySelector(
                LazyRaider.CreateBTPS_NotifyAndShortCircuitWhenCombatDisabled(),
                CreateBTPS.BWcoreFixup_WaitForHarvestComplete(),
                TargetSelect.CreateBTPS_UpdateForBattlefieldConditions(),

                SorcererLightning_SageTelekinetics_Combat()
                );
        }

        [Behavior(BehaviorType.Combat)]
        [Class(CharacterClass.Inquisitor, AdvancedClass.Sorcerer, SkillTreeId.SorcererLightning)]
        [Class(CharacterClass.Consular, AdvancedClass.Sage, SkillTreeId.SageTelekinetics)]
        public static Composite SorcererLightning_SageTelekinetics_Combat()
        {
            return new PrioritySelector(
                LazyRaider.CreateBTPS_NotifyAndShortCircuitWhenCombatDisabled(),
                TargetSelect.CreateBTPS_UpdateForBattlefieldConditions(),

                CreateBTPS.StopWithinRangeAndLoS(target => MyTarget, Global.Distance.Ranged),

                //General
                Cast("Polarity Shift"),
                Cast("Unbreakable Will", unbreakableWillWhen => Global.CCBreak),
                Cast("Recklessness"),//Buff for 2 Mirrors

                //Interrupt
                new Decorator(doInterruptWhen => InterruptTarget != null,
                    new PrioritySelector(
                        Cast("Jolt", joltOn => InterruptTarget),
                        Cast("Electrocute", electrocuteOn => InterruptTarget)
                        )),

                //CC
                Cast("Whirlwind", whirlwindOn => CCTarget, whirlwindWhen => CCTarget != null),
                Cast("Overload", overloadWhen => Me.MobCountAround(Global.Distance.MeleeAoE) >= 3 && Me.MobCountAttacking() >= 3),

                //Dispell
                Cast("Purge", purgeOn => DispellTarget, purgeWhen => DispellTarget != null),

                //Healing
                Cast("Static Barrier", staticBarrierOn => ShieldTarget, staticBarrierWhen => ShieldTarget != null),//Shield
                new Decorator(whenHealNeeded => HealTarget != null,
                    new PrioritySelector
                    (
                        Cast("Dark Heal", darkHealOn => HealTarget, darkHealWhen => HealTarget.HealthPercent <= Global.Health.Low),
                        Cast("Resurgence", resurgenceOn => HealTarget, resurgenceWhen => HealTarget.HealthPercent <= Global.Health.High && !HealTarget.HasMirrorBuff("Resurgence")),//Low Heal & HoT
                        Cast("Innervate", innervateOn => HealTarget, innervateWhen => HealTarget.HealthPercent <= Global.Health.Mid),//Low Heal & HoT
                        Cast("Dark Infusion", darkInfusionOn => HealTarget, darkInfusionWhen => HealTarget.HealthPercent <= Global.Health.Mid)
                    )),

                //Offensive
                Cast("Chain Lightning", chainLightningWhen => MyTarget.MobCountAround(Global.Distance.MeleeAoE) >= 3 || Me.HasMirrorBuff("Lightning Storm")),
                Cast("Crushing Darkness", crushingDarknessWhen => MyTarget.HealthPercent >= 40),
                CreateBTPS.DebuffAllTargets("Affliction", "Affliction (Force)"),
                Cast("Lightning Strike", lightningStrikeWhen => (Me.HasMirrorAbility("Subversion") && !Me.HasMirrorBuffStacks("Subversion", 3, b => (b.TimeLeft >= TimeSpan.FromSeconds(6))))),
                Cast("Thundering Blast"),
                Cast("Force Lightning", forceLightningWhen => Me.HasImpliedMirrorBuff("Lightning Barrage")),
                Cast("Shock"),
                Cast("Lightning Strike"),

                //Movement
                CreateBTPS.MoveWithinRangeAndLoS(target => MyTarget, Global.Distance.Ranged)
                );
        }

        [Behavior(BehaviorType.OutOfCombat)]
        [Class(CharacterClass.Inquisitor, AdvancedClass.Sorcerer, SkillTreeId.SorcererLightning)]
        [Class(CharacterClass.Consular, AdvancedClass.Sage, SkillTreeId.SageTelekinetics)]
        public static Composite SorcererLightning_SageTelekinetics_OutOfCombat()
        {
            // NB: Apparently, BWcore will call this routine when in combat on occasion.  It is also called while we're pulling.
            return (new PrioritySelector(
                TargetSelect.CreateBTPS_UpdateForBattlefieldConditions(),
                new Decorator(oocBuffWhen => !Me.IsMounted,
                    new PrioritySelector(
                        BuffSelf("Force Speed", forceSpeedWhen => Me.IsMoving)
                        ))
                ));
        }
    }
}